<!DOCTYPE html>
<html lang="en">
  <head>
    <!-- AdThrive Head Tag Manual -->
    <script data-no-optimize="1" data-cfasync="false">
      (function (w, d) {
        w.adthrive = w.adthrive || {};
        w.adthrive.cmd = w.adthrive.cmd || [];
        w.adthrive.plugin = "adthrive-ads-manual";
        w.adthrive.host = "ads.adthrive.com";
        var s = d.createElement("script");
        s.async = true;
        s.referrerpolicy = "no-referrer-when-downgrade";
        s.src =
          "https://" +
          w.adthrive.host +
          "/sites/643436a4e6d20859e40a446b/ads.min.js?referrer=" +
          w.encodeURIComponent(w.location.href) +
          "&cb=" +
          (Math.floor(Math.random() * 100) + 1);
        var n = d.getElementsByTagName("script")[0];
        n.parentNode.insertBefore(s, n);
      })(window, document);
    </script>
    <!-- End of AdThrive Head Tag -->

    <!-- Global site tag (gtag.js) - Google Analytics -->

    <script
      async
      src="https://www.googletagmanager.com/gtag/js?id=UA-79254642-6"
    ></script>

    <script>
      window.dataLayer = window.dataLayer || [];
      function gtag() {
        dataLayer.push(arguments);
      }
      gtag("js", new Date());

      gtag("config", "UA-79254642-6");
    </script>

    <meta charset="utf-8" />
    <title>Double circular barplot in d3.js</title>
    <meta
      name="viewport"
      content="width=device-width, initial-scale=1, shrink-to-fit=no"
    />
    <meta
      name="description"
      content="Using d3.js to create a circular barplot with 2 data series facing each other. A post with explanation and reproducible code. Example with code (d3.js v4 and v6)."
    />
    <meta
      name="keywords"
      content="Data, Dataviz, Datavisualization, Javascript, JS, d3.js, circular barplot"
    />
    <meta name="author" content="Yan Holtz" />
    <link rel="icon" href="../img/logo/D3_single_small.png" />

    <meta property="og:title" content="Double circular barplot in d3.js" />
    <meta
      property="og:image"
      content="https://www.d3-graph-gallery.com/img/logo/D3_full_medium.png"
    />
    <meta
      property="og:description"
      content="Using d3.js to create a circular barplot with 2 data series facing each other. A post with explanation and reproducible code. Example with code (d3.js v4 and v6)."
    />

    <!-- Bootstrap core CSS -->
    <link href="../vendor/bootstrap/css/bootstrap.min.css" rel="stylesheet" />

    <!-- Custom fonts for this template -->
    <link
      href="../vendor/font-awesome/css/font-awesome.min.css"
      rel="stylesheet"
      type="text/css"
    />

    <!-- Custom styles for this template -->
    <link href="../css/agency.css" rel="stylesheet" />

    <!-- PRISM -->
    <script src="../LIB/prism.js"></script>
    <link href="../LIB/prism.css" rel="stylesheet" />

    <!-- JQUERY -->
    <script src="../vendor/jquery/jquery.min.js"></script>

    <!-- HTML TO CANVAS -->
    <script src="../js/html2canvas.js"></script>

    <!-- Function to parse html and js code chunks made by Yan Holtz -->
    <script src="../js/myParser.js"></script>

    <!-- Function for radial charts -->
    <script src="../LIB/d3-scale-radial.js"></script>
  </head>

  <body id="page-top">
    <!-- THIS ALLOWS TO INSERT THE MENU THAT IS STORED IN A MENU.HTML FILE-->
    <nav class="navbar navbar-expand-lg fixed-top" id="mainNav"></nav>
    <script>
      $(function () {
        $("#mainNav").load("../html_chunk/menu.html");
      });
    </script>

    <!-- THIS ALLOWS TO INSERT THE MODAL OF THE MENU THAT IS STORED IN A MENU_MODAL.HTML FILE-->
    <div id="modal_menu_insertion"></div>
    <script>
      $(function () {
        $("#modal_menu_insertion").load("../html_chunk/menu_modal.html");
      });
    </script>

    <!-- Header -->
    <header class="masthead">
      <div class="textlanding">
        <h1>Double circular barplot</h1>
        <hr class="short_hr" />
        <br />
        <ul class="list-inline social-buttons">
          <li class="list-inline-item">
            <a href="https://twitter.com/R_Graph_Gallery">
              <i class="fa fa-twitter"></i>
            </a>
          </li>
          <li class="list-inline-item social-buttons">
            <a href="https://github.com/holtzy">
              <i class="fa fa-github" style="color: white"></i>
            </a>
          </li>
          <li class="list-inline-item social-buttons">
            <a href="https://www.linkedin.com/in/yan-holtz-2477534a/">
              <i class="fa fa-linkedin"></i>
            </a>
          </li>
          <li class="list-inline-item social-buttons">
            <a href="https://www.yan-holtz.com">
              <i class="fa fa-home"></i>
            </a>
          </li>
        </ul>
        <br /><br />
        <p style="max-width: 700px; margin: auto">
          This post describes how to build a special
          <a href="../circular_barplot.html">circular barplot</a> with d3.js.
          Two numeric variables are available for each group of the dataset, and
          are facing each other on the chart. This example illustrates the
          distortion that bars face on this type of chart. Visit
          <a href="https://www.data-to-viz.com/graph/circularbarplot.html"
            >data-to-viz.com</a
          >
          for more info. This example works with d3.js <code>v4</code> and
          <code>v6</code>
        </p>
        <br />
        <a
          class="btn btn-secondary btn-md text-uppercase"
          href="../circular_barplot.html"
          >Circular barplot section</a
        >
        <button
          class="btn btn-secondary btn-md text-uppercase"
          onclick="myCodeDownload('chart_example_from_d3-graph-gallery.html', 'code-html-v4', 'code-js-v4')"
        >
          Download code
        </button>
      </div>
    </header>

    <section class="bg" style="padding-top: 20px; padding-bottom: 20px">
      <div class="container">
        <div class="row">
          <!-- ==================== GRAPH SECTION = WHERE THE GRAPH APPEARS ==================== -->

          <div class="col-lg-5 .align-middle">
            <div style="position: -webkit-sticky; position: sticky; top: 120px">
              <div class="bg-light" id="result"></div>
              <br />
              <div>
                <h5>Steps:</h5>
                <ul>
                  <br />
                  <li>
                    This example is pretty straight forward to build if you
                    already understood the previous
                    <a href="circular_barplot_label.html"
                      >circular barplot with label</a
                    >.
                  </li>
                  <br />
                  <li>
                    It just adds a second Y scale oriented in the other side:
                    from <code>innerRadius</code> to ~0
                  </li>
                  <br />
                  <li>
                    <u>Note</u>: here the same variable is used for the inner
                    and the outer part. It illustrates the main caveat of
                    circular barcharts: see how the bar size is distorted?
                  </li>
                </ul>
              </div>
            </div>
          </div>

          <!-- ================================================================================= -->

          <!-- ==================== CODE SECTION = WHERE THE CODE APPEARS ==================== -->
          <div class="col-lg-7 text-center .align-middle">
            <div class="v4-v6-toggle">
              <button
                id="button-show-v4"
                onclick="showCodeVersion('v4')"
                type="button"
                class="btn btn-secondary btn-sm active"
              >
                d3 v4
              </button>
              <span> | </span>
              <button
                id="button-show-v6"
                onclick="showCodeVersion('v6')"
                type="button"
                class="btn btn-secondary btn-sm"
              >
                d3 v6
              </button>
            </div>

            <!-- ========= show html code ============== -->
            <aside
              style="position: -webkit-sticky; position: sticky; top: 120px"
            >
              &larr; Edit me!
            </aside>
            <pre
              class="language-html d-none d3v4-chunk"
            ><code id="code-html-v4" contenteditable="true"><xmp><!DOCTYPE html>
<meta charset="utf-8">

<!-- Load d3.js -->
<script src="https://d3js.org/d3.v4.js"></script>

<!-- Function for radial charts -->
<script src="https://cdn.jsdelivr.net/gh/holtzy/D3-graph-gallery@master/LIB/d3-scale-radial.js"></script>

<!-- Create a div where the graph will take place -->
<div id="my_dataviz"></div>

</xmp></code></pre>

            <pre
              class="language-html d-none d3v6-chunk"
            ><code id="code-html-v6" contenteditable="true"><xmp><!DOCTYPE html>
<meta charset="utf-8">

<!-- Load d3.js -->
<script src="https://d3js.org/d3.v6.js"></script>

<!-- Create a div where the graph will take place -->
<div id="my_dataviz"></div>

</xmp></code></pre>
            <!-- ==================================== -->

            <!-- ========= show JS code ==============  -->
            <pre
              class="language-js d-none d3v4-chunk"
            ><code id="code-js-v4" contenteditable="true"><xmp><script>

// set the dimensions and margins of the graph
var margin = {top: 100, right: 0, bottom: 0, left: 0},
    width = 460 - margin.left - margin.right,
    height = 460 - margin.top - margin.bottom,
    innerRadius = 90,
    outerRadius = Math.min(width, height) / 2;   // the outerRadius goes from the middle of the SVG area to the border

// append the svg object
var svg = d3.select("#my_dataviz")
  .append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
  .append("g")
    .attr("transform", "translate(" + (width / 2 + margin.left) + "," + (height / 2 + margin.top) + ")");

d3.csv("https://raw.githubusercontent.com/holtzy/data_to_viz/master/Example_dataset/7_OneCatOneNum.csv", function(data) {

  // X scale: common for 2 data series
  var x = d3.scaleBand()
      .range([0, 2 * Math.PI])    // X axis goes from 0 to 2pi = all around the circle. If I stop at 1Pi, it will be around a half circle
      .align(0)                  // This does nothing
      .domain(data.map(function(d) { return d.Country; })); // The domain of the X axis is the list of states.

  // Y scale outer variable
  var y = d3.scaleRadial()
      .range([innerRadius, outerRadius])   // Domain will be define later.
      .domain([0, 13000]); // Domain of Y is from 0 to the max seen in the data

  // Second barplot Scales
  var ybis = d3.scaleRadial()
      .range([innerRadius, 5])   // Domain will be defined later.
      .domain([0, 13000]);

  // Add the bars
  svg.append("g")
    .selectAll("path")
    .data(data)
    .enter()
    .append("path")
      .attr("fill", "#69b3a2")
      .attr("class", "yo")
      .attr("d", d3.arc()     // imagine your doing a part of a donut plot
          .innerRadius(innerRadius)
          .outerRadius(function(d) { return y(d['Value']); })
          .startAngle(function(d) { return x(d.Country); })
          .endAngle(function(d) { return x(d.Country) + x.bandwidth(); })
          .padAngle(0.01)
          .padRadius(innerRadius))

  // Add the labels
  svg.append("g")
      .selectAll("g")
      .data(data)
      .enter()
      .append("g")
        .attr("text-anchor", function(d) { return (x(d.Country) + x.bandwidth() / 2 + Math.PI) % (2 * Math.PI) < Math.PI ? "end" : "start"; })
        .attr("transform", function(d) { return "rotate(" + ((x(d.Country) + x.bandwidth() / 2) * 180 / Math.PI - 90) + ")"+"translate(" + (y(d['Value'])+10) + ",0)"; })
      .append("text")
        .text(function(d){return(d.Country)})
        .attr("transform", function(d) { return (x(d.Country) + x.bandwidth() / 2 + Math.PI) % (2 * Math.PI) < Math.PI ? "rotate(180)" : "rotate(0)"; })
        .style("font-size", "11px")
        .attr("alignment-baseline", "middle")

  // Add the second series
  svg.append("g")
    .selectAll("path")
    .data(data)
    .enter()
    .append("path")
      .attr("fill", "red")
      .attr("d", d3.arc()     // imagine your doing a part of a donut plot
          .innerRadius( function(d) { return ybis(0) })
          .outerRadius( function(d) { return ybis(d['Value']); })
          .startAngle(function(d) { return x(d.Country); })
          .endAngle(function(d) { return x(d.Country) + x.bandwidth(); })
          .padAngle(0.01)
          .padRadius(innerRadius))

});

</script></xmp></code></pre>
            <!-- ==================================== -->

            <!-- ========= show JS code v6 ==============  -->
            <pre
              class="language-js d-none d3v6-chunk"
            ><code id="code-js-v6" contenteditable="true"><xmp><script>

// set the dimensions and margins of the graph
const margin = {top: 100, right: 0, bottom: 0, left: 0},
    width = 460 - margin.left - margin.right,
    height = 460 - margin.top - margin.bottom,
    innerRadius = 90,
    outerRadius = Math.min(width, height) / 2;   // the outerRadius goes from the middle of the SVG area to the border

// append the svg object
const svg = d3.select("#my_dataviz")
  .append("svg")
    .attr("width", width + margin.left + margin.right)
    .attr("height", height + margin.top + margin.bottom)
  .append("g")
    .attr("transform", `translate(${width/2 + margin.left}, ${height/2 + margin.top})`);

d3.csv("https://raw.githubusercontent.com/holtzy/data_to_viz/master/Example_dataset/7_OneCatOneNum.csv").then( function(data) {

  // X scale: common for 2 data series
  const x = d3.scaleBand()
      .range([0, 2 * Math.PI])    // X axis goes from 0 to 2pi = all around the circle. If I stop at 1Pi, it will be around a half circle
      .align(0)                  // This does nothing
      .domain(data.map(d => d.Country)); // The domain of the X axis is the list of states.

  // Y scale outer variable
  const y = d3.scaleRadial()
      .range([innerRadius, outerRadius])   // Domain will be define later.
      .domain([0, 13000]); // Domain of Y is from 0 to the max seen in the data

  // Second barplot Scales
  const ybis = d3.scaleRadial()
      .range([innerRadius, 5])   // Domain will be defined later.
      .domain([0, 13000]);

  // Add the bars
  svg.append("g")
    .selectAll("path")
    .data(data)
    .join("path")
      .attr("fill", "#69b3a2")
      .attr("class", "yo")
      .attr("d", d3.arc()     // imagine your doing a part of a donut plot
          .innerRadius(innerRadius)
          .outerRadius(d => y(d['Value']))
          .startAngle(d => x(d.Country))
          .endAngle(d => x(d.Country) + x.bandwidth())
          .padAngle(0.01)
          .padRadius(innerRadius))

  // Add the labels
  svg.append("g")
      .selectAll("g")
      .data(data)
      .join("g")
        .attr("text-anchor", function(d) { return (x(d.Country) + x.bandwidth() / 2 + Math.PI) % (2 * Math.PI) < Math.PI ? "end" : "start"; })
        .attr("transform", function(d) { return "rotate(" + ((x(d.Country) + x.bandwidth() / 2) * 180 / Math.PI - 90) + ")"+"translate(" + (y(d['Value'])+10) + ",0)"; })
      .append("text")
        .text(d => d.Country)
        .attr("transform", function(d) { return (x(d.Country) + x.bandwidth() / 2 + Math.PI) % (2 * Math.PI) < Math.PI ? "rotate(180)" : "rotate(0)"; })
        .style("font-size", "11px")
        .attr("alignment-baseline", "middle")

  // Add the second series
  svg.append("g")
    .selectAll("path")
    .data(data)
    .join("path")
      .attr("fill", "red")
      .attr("d", d3.arc()     // imagine your doing a part of a donut plot
          .innerRadius( d => ybis(0))
          .outerRadius( d => ybis(d['Value']))
          .startAngle(d => x(d.Country))
          .endAngle(d => x(d.Country) + x.bandwidth())
          .padAngle(0.01)
          .padRadius(innerRadius))

});

</script></xmp></code></pre>
            <!-- ==================================== -->
          </div>
        </div>
      </div>
    </section>
    <br />

    <!-- ============================ -->

    <!-- ============================ RELATED BLOCKS ============================ -->

    <section class="bg-light" style="padding-top: 70px; padding-bottom: 70px">
      <div class="container">
        <div class="row">
          <div class="col-lg-5 text-center align-self-center">
            <h3 class="text-uppercase">Related blocks &rarr;</h3>
          </div>
          <div class="col-lg-5">
            <ul>
              <li>
                <i>d3-scale documentation- </i>by
                <a href="https://github.com/d3/d3-scale">Mike Bostock</a>
              </li>
              <br />
              <li>
                <i>discussion on d3.scaleRadial - </i>by
                <a href="https://github.com/d3/d3-scale/issues/90"
                  >Mike Bostock and others</a
                >
              </li>
              <br />
              <li>
                <i>Radial Stacked Bar - </i>by
                <a
                  href="https://bl.ocks.org/mbostock/6fead6d1378d6df5ae77bb6a719afcb2"
                  >Mike Bostock</a
                >
              </li>
            </ul>
          </div>
        </div>
      </div>
    </section>

    <!-- ============================ CONTACT SECTION ============================ -->

    <!-- ANCHOR -->
    <a name="contactanchor"></a>

    <section id="contact" class="bg" style="background-color: white"></section>

    <!-- THIS ALLOWS TO INSERT THE CONTACT CHUNK THAT IS STORED IN A CONTACT.HTML FILE-->
    <script>
      $(function () {
        $("#contact").load("../html_chunk/contact.html");
      });
    </script>

    <!-- ============================ FOOTER SECTION ============================ -->
    <footer class="bg-light" id="myFooter"></footer>

    <!-- Start Added by AdThrive -->
    <script
      type="text/javascript"
      async
      src="https://btloader.com/tag?o=5698917485248512&upapi=true&domain=d3-graph-gallery.com"
    ></script>
    <script>
      !(function () {
        "use strict";
        var e;
        (e = document),
          (function () {
            var t, n;
            function r() {
              var t = e.createElement("script");
              (t.src =
                "https://cafemedia-com.videoplayerhub.com/galleryplayer.js"),
                e.head.appendChild(t);
            }
            function a() {
              var t = e.cookie.match("(^|[^;]+)\s*__adblocker\s*=\s*([^;]+)");
              return t && t.pop();
            }
            function c() {
              clearInterval(n);
            }
            return {
              init: function () {
                var e;
                "true" === (t = a())
                  ? r()
                  : ((e = 0),
                    (n = setInterval(function () {
                      (100 !== e && "false" !== t) || c(),
                        "true" === t && (r(), c()),
                        (t = a()),
                        e++;
                    }, 50)));
              },
            };
          })().init();
      })();
    </script>
    <!-- End Added by AdThrive -->

    <!-- THIS ALLOWS TO INSERT THE FOOTER THAT IS STORED IN A FOOTER.HTML FILE-->
    <script>
      $(function () {
        $("#myFooter").load("../html_chunk/footer.html");
      });
    </script>

    <!-- ============================ -->

    <!-- ============================ JAVASCRIPT SECTION ============================ -->

    <!-- Bootstrap core JavaScript -->
    <script src="../vendor/bootstrap/js/bootstrap.bundle.min.js"></script>

    <!-- Custom scripts for this template -->
    <script src="../js/agency.min.js"></script>

    <!-- Activate the bootstrap tooltip, must be after jQuery load -->
    <script>
      $(function () {
        $('[data-toggle="tooltip"]').tooltip();
      });
    </script>

    <script>
      showCodeVersion("v4");
    </script>
  </body>
</html>
